import json
import random
import time

from utils.AssertUtil import AssertUtil
from utils.YamlUtil import YamlUtil
from utils.log_util import logger


class ExtractUtil:
    """
    解析yaml中的抽象函数
    """
    def __init__(self):
        self.jsonpath_util = AssertUtil()
        self.yaml_util = YamlUtil()

    def extract_data(self, res, extract):
        """
        根据extract表达式，获取接口内容并存入yaml
        :param res: res.json()
        :param extract: eg $.token
        :return:
        """
        # 获取订单id --> 将作为订单详情的url地址
        if extract:

            for key, expression in extract.items():
                try:
                    value = self.jsonpath_util.extract_by_jsonpath(res, expression)
                    # 写入value
                    self.yaml_util.write_extra_yaml({key: value})
                except Exception as e:
                    logger.error(f"变量{key}写入extract.yaml失败，请检查，error={e}")

    def get_extract_value(self, key):
        """从extract.yaml中获取内容  data[key]对应的是单个值--返回该值 多个值则返回数组"""
        try:
            data = self.yaml_util.read_extract_yaml()
            return data[key]
        except Exception as e:
            logger.error(f"从yaml中根据{key}获取不到内容，error={e}")

    def extract_url(self, url):
        # /orders/${get_extract_value(order_id)}/
        if "${" in url and "}" in url:
            return self.process_data(url)
        return url

    def process_data(self, data):
        """
        处理 ${函数} ---> 改进：利用for循环进行多次判断
        注意：只针对yaml文件中定义的次数，而函数${}中的参数则默认使用第一个，无法循环
        解析函数 及 其中参数（用写入的yaml文件中读取） ---> 用读取的值将函数中参数名替换  因此！读取到的值data必须为str类型！！
        """
        for i in range(data.count("${")):
            if '${' in data and '}' in data:
                start_index = data.index('$')
                end_index = data.index("}")
                # 获取函数中的方法
                func_full_name = data[start_index: end_index + 1]
                # 获取函数名
                func_name = data[start_index + 2: data.index('(')]
                # 获取函数中的参数
                func_params = data[data.index('(') + 1: data.index(')')]

                # extract_data = getattr(self, func_name)(func_params)
                # 先进行getattr
                extract_data = getattr(self, func_name, None)
                if extract_data is not None:
                #     # 将参数拆分为列表
                    func_params = func_params.split(',') if func_params else []
                #     # 尝试将参数转换为整数,能转则进行转换
                    func_params = [int(param) if param.isdigit() else param for param in func_params]
                    extract_data = extract_data(*func_params)
                    # 确保参数不是数组
                    if isinstance(extract_data, list):
                        data = data.replace(func_full_name, str(extract_data[0]))
                # data = data.replace(func_full_name, str(extract_data[0]))
                    else:
                        data = data.replace(func_full_name, str(extract_data))
        return data

    def extract_case(self, case_info):
        """输入为字典类型的param数据 ---> 需要拿到value ---> 进行${}处理"""
        # 转成str类型  json.dumps():用于将 Python 对象编码成 JSON 格式的字符串--返回字符串
        #             json_dump():----将这个字符串写入到一个文件描述符（file-like object）中，而不是直接返回这个字符串。
        str_case_info = json.dumps(case_info)
        # 处理 ${}
        data = self.process_data(str_case_info)
        # 换回json类型
        return json.loads(data)

    def get_time(self):
        timestamp = int(time.time())
        return timestamp

    def get_random(self, num1, num2):
        return random.randint(num1, num2)

    def get_add(self, num1, num2):
        return num1 + num2


if __name__ == '__main__':
    # print(ExtractUtil().get_extract_value())
    # print(getattr(ExtractUtil(), "get_random")("1111", "2222"))
    print(ExtractUtil().process_data("${get_time()}"))
    pass
